/* * JBoss, Home of Professional Open Source * * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.xnio.nativeimpl; import java.io.IOError; import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; import org.jboss.logging.Logger; import org.xnio.Buffers; import org.xnio.LocalSocketAddress; import static org.xnio.Bits.allAreSet; /** * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a> */ final class Native { static final Logger log = Logger.getLogger("org.xnio.native"); // init static final int DEAD_FD; static final int EAGAIN; static final int EINTR; static final int EBADF; static final int UNIX_PATH_LEN; static final boolean HAS_EPOLL; static final boolean HAS_KQUEUE; static final boolean HAS_DEV_POLL; static final boolean HAS_PORTS; static final boolean HAS_SPLICE; static final boolean HAS_SENDFILE; static final boolean HAS_CORK; static final boolean SAFE_GC; static final boolean EXTRA_TRACE; static { try { System.loadLibrary("xnio"); } catch (Error error) { log.debugf("XNIO native not available on this platform (%s)", error); throw error; } final int[] constants = init(); try { DEAD_FD = testAndThrow(constants[0]); } catch (IOException e) { throw new IOError(e); } EAGAIN = constants[1]; EINTR = constants[2]; UNIX_PATH_LEN = constants[3]; HAS_EPOLL = allAreSet(constants[4], 0b0000001); HAS_KQUEUE = allAreSet(constants[4], 0b0000010); HAS_DEV_POLL = allAreSet(constants[4], 0b0000100); HAS_PORTS = allAreSet(constants[4], 0b0001000); HAS_SPLICE = allAreSet(constants[4], 0b0010000); HAS_SENDFILE = allAreSet(constants[4], 0b0100000); HAS_CORK = allAreSet(constants[4], 0b1000000); SAFE_GC = AccessController.doPrivileged(new BooleanPropertyAction("xnio.native.safe-gc")).booleanValue(); EXTRA_TRACE = AccessController.doPrivileged(new BooleanPropertyAction("xnio.native.extra-trace")).booleanValue(); EBADF = constants[5]; } private Native() {} private static native int[] init(); // POSIX-ish /** * Call the UNIX dup2 system call. * * @param oldFd the old FD * @param newFd the new FD * @return the result */ static native int dup2(int oldFd, int newFd, Object keepAlive); /** * Call the UNIX dup system call. * * @param oldFd the old FD * @return the new FD or error */ static native int dup(int oldFd, Object keepAlive); /** * Close the FD. * * @param fd the FD to close * @return 0 for okay, a negative error code for error */ static native int close(int fd, Object keepAlive); /** * Get a string for an error code. * * @param err a negative or positive error code * @return the string */ static native String strError(int err); /** * Shut down a socket. * * @param fd the socket FD * @param read {@code true} to shut down reads * @param write {@code true} to shut down writes * @return 0 for okay, a negative error code for error */ static native int shutdown(int fd, boolean read, boolean write, Object keepAlive); static native int await2(final int fd, final boolean writes, Object keepAlive); static native int await3(final int fd, final boolean writes, final long millis, Object keepAlive); static native byte[] getSockName(final int fd, Object keepAlive); static native byte[] getPeerName(final int fd, Object keepAlive); // read static native long readLong(final int fd, Object keepAlive); static native int readD(final int fd, ByteBuffer b1, int p1, int l1, Object keepAlive); static native long readDD(final int fd, ByteBuffer b1, int p1, int l1, ByteBuffer b2, int p2, int l2, Object keepAlive); static native long readDDD(final int fd, ByteBuffer b1, int p1, int l1, ByteBuffer b2, int p2, int l2, ByteBuffer b3, int p3, int l3, Object keepAlive); static native int readH(final int fd, byte[] b1, int p1, int l1, Object keepAlive); static native long readHH(final int fd, byte[] b1, int p1, int l1, byte[] b2, int p2, int l2, Object keepAlive); static native long readHHH(final int fd, byte[] b1, int p1, int l1, byte[] b2, int p2, int l2, byte[] b3, int p3, int l3, Object keepAlive); // slower static native long readMisc(final int fd, ByteBuffer[] buffers, int offs, int len, Object keepAlive); static int readSingle(final int fd, ByteBuffer buf1, Object keepAlive) throws IOException { if (buf1.isReadOnly()) { throw new ReadOnlyBufferException(); } final int cnt; final int pos1 = buf1.position(); final int lim1 = buf1.limit(); if (pos1 == lim1) return 0; if (buf1.isDirect()) { cnt = testAndThrowRead(readD(fd, buf1, pos1, lim1, keepAlive)); if (EXTRA_TRACE) log.tracef("Read(%d): %d", fd, cnt); } else { cnt = testAndThrowRead(readH(fd, buf1.array(), pos1 + buf1.arrayOffset(), lim1 + buf1.arrayOffset(), keepAlive)); if (EXTRA_TRACE) log.tracef("Read(%d): %d", fd, cnt); } if (cnt > 0) { buf1.position(pos1 + cnt); } return cnt; } static long readScatter(final int fd, ByteBuffer[] buffers, int offs, int len, Object keepAlive) throws IOException { if (len <= 0L) { if (EXTRA_TRACE) log.tracef("Read(%d): zero array length", fd); return 0L; } final ByteBuffer buf1 = buffers[offs]; if (buf1.isReadOnly()) { throw new ReadOnlyBufferException(); } final int pos1 = buf1.position(); final int lim1 = buf1.limit(); final boolean dir1 = buf1.isDirect(); if (len == 1) { if (pos1 == lim1) return 0; final int cnt; if (dir1) { cnt = testAndThrowRead(readD(fd, buf1, pos1, lim1, keepAlive)); } else { final int off1 = buf1.arrayOffset(); cnt = testAndThrowRead(readH(fd, buf1.array(), pos1 + off1, lim1 + off1, keepAlive)); } if (cnt > 0) { buf1.position(pos1 + cnt); } if (EXTRA_TRACE) log.tracef("Read(%d): %d", fd, cnt); return cnt; } final ByteBuffer buf2 = buffers[offs + 1]; if (buf2.isReadOnly()) { throw new ReadOnlyBufferException(); } final int pos2 = buf2.position(); final int lim2 = buf2.limit(); final boolean dir2 = buf2.isDirect(); if (len == 2) { if (pos1 == lim1 && pos2 == lim2) return 0; final long cnt; if (dir1 && dir2) { cnt = testAndThrowRead(readDD(fd, buf1, pos1, lim1, buf2, pos2, lim2, keepAlive)); } else if (!dir1 && !dir2) { final int off1 = buf1.arrayOffset(); final int off2 = buf2.arrayOffset(); cnt = testAndThrowRead(readHH(fd, buf1.array(), pos1 + off1, lim1 + off1, buf2.array(), pos2 + off2, lim2 + off2, keepAlive)); } else { cnt = testAndThrowRead(readMisc(fd, buffers, offs, len, keepAlive)); } if (cnt > 0L) { if (pos1 + cnt <= lim1) { buf1.position(pos1 + (int) cnt); } else { buf1.position(lim1); buf2.position(pos2 + (int) (cnt - (lim1 - pos1))); } } if (EXTRA_TRACE) log.tracef("Read(%d): %d", fd, cnt); return cnt; } final ByteBuffer buf3 = buffers[offs + 2]; if (buf3.isReadOnly()) { throw new ReadOnlyBufferException(); } final int pos3 = buf3.position(); final int lim3 = buf3.limit(); final boolean dir3 = buf3.isDirect(); if (len == 3) { if (pos1 == lim1 && pos2 == lim2 && pos3 == lim3) return 0; final long cnt; if (dir1 && dir2 && dir3) { cnt = testAndThrowRead(readDDD(fd, buf1, pos1, lim1, buf2, pos2, lim2, buf3, pos3, lim3, keepAlive)); } else if (!dir1 && !dir2 && !dir3) { final int off1 = buf1.arrayOffset(); final int off2 = buf2.arrayOffset(); final int off3 = buf3.arrayOffset(); cnt = testAndThrowRead(readHHH(fd, buf1.array(), pos1 + off1, lim1 + off1, buf2.array(), pos2 + off2, lim2 + off2, buf3.array(), pos3 + off3, lim3 + off3, keepAlive)); } else { cnt = testAndThrowRead(readMisc(fd, buffers, offs, len, keepAlive)); } if (cnt > 0L) { if (pos1 + cnt <= lim1) { buf1.position(pos1 + (int) cnt); } else if (pos1 + cnt - lim1 <= lim2) { buf1.position(lim1); buf2.position(pos2 + (int) (cnt - (lim1 - pos1))); } else { buf1.position(lim1); buf2.position(lim2); buf3.position(pos3 + (int) (cnt - (lim1 - pos1 + lim2 - pos2))); } } if (EXTRA_TRACE) log.tracef("Read(%d): %d", fd, cnt); return cnt; } for (int i = 3; i < len; i ++) { if (buffers[i].isReadOnly()) { throw new ReadOnlyBufferException(); } } if (! Buffers.hasRemaining(buffers, offs, len)) return 0; final long cnt = testAndThrowRead(readMisc(fd, buffers, offs, len, keepAlive)); Buffers.trySkip(buffers, offs, len, cnt); if (EXTRA_TRACE) log.tracef("Read(%d): %d", fd, cnt); return cnt; } // write static native int writeLong(final int fd, final long value); static native int writeD(final int fd, ByteBuffer b1, int p1, int l1); static native long writeDD(final int fd, ByteBuffer b1, int p1, int l1, ByteBuffer b2, int p2, int l2); static native long writeDDD(final int fd, ByteBuffer b1, int p1, int l1, ByteBuffer b2, int p2, int l2, ByteBuffer b3, int p3, int l3); static native int writeH(final int fd, byte[] b1, int p1, int l1); static native long writeHH(final int fd, byte[] b1, int p1, int l1, byte[] b2, int p2, int l2); static native long writeHHH(final int fd, byte[] b1, int p1, int l1, byte[] b2, int p2, int l2, byte[] b3, int p3, int l3); // slower static native long writeMisc(final int fd, ByteBuffer[] buffers, int offs, int len); static native int flushTcpCork(final int fd); static int writeSingle(final int fd, ByteBuffer buf1) throws IOException { final int cnt; final int pos1 = buf1.position(); if (buf1.isDirect()) { cnt = testAndThrowWrite(writeD(fd, buf1, pos1, buf1.limit())); } else { cnt = testAndThrowWrite(writeH(fd, buf1.array(), pos1 + buf1.arrayOffset(), buf1.limit() + buf1.arrayOffset())); } if (cnt > 0) { buf1.position(pos1 + cnt); } if (EXTRA_TRACE) log.tracef("Write(%d): %d", fd, cnt); return cnt; } static long writeGather(final int fd, ByteBuffer[] buffers, int offs, int len) throws IOException { if (len <= 0L) { if (EXTRA_TRACE) log.tracef("Write(%d): zero array length", fd); return 0L; } final ByteBuffer buf1 = buffers[offs]; final int pos1 = buf1.position(); final int lim1 = buf1.limit(); final boolean dir1 = buf1.isDirect(); if (len == 1) { final int cnt; if (dir1) { cnt = testAndThrowWrite(writeD(fd, buf1, pos1, lim1)); } else { final int off1 = buf1.arrayOffset(); cnt = testAndThrowWrite(writeH(fd, buf1.array(), pos1 + off1, lim1 + off1)); } if (cnt > 0) { buf1.position(pos1 + cnt); } if (EXTRA_TRACE) log.tracef("Write(%d): %d", fd, cnt); return cnt; } final ByteBuffer buf2 = buffers[offs + 1]; final int pos2 = buf2.position(); final int lim2 = buf2.limit(); final boolean dir2 = buf2.isDirect(); if (len == 2) { final long cnt; if (dir1 && dir2) { cnt = testAndThrowWrite(writeDD(fd, buf1, pos1, lim1, buf2, pos2, lim2)); } else if (!dir1 && !dir2) { final int off1 = buf1.arrayOffset(); final int off2 = buf2.arrayOffset(); cnt = testAndThrowWrite(writeHH(fd, buf1.array(), pos1 + off1, lim1 + off1, buf2.array(), pos2 + off2, lim2 + off2)); } else { cnt = testAndThrowWrite(writeMisc(fd, buffers, offs, len)); } if (cnt > 0L) { if (pos1 + cnt <= lim1) { buf1.position(pos1 + (int) cnt); } else { buf1.position(lim1); buf2.position(pos2 + (int) (cnt - (lim1 - pos1))); } } if (EXTRA_TRACE) log.tracef("Write(%d): %d", fd, cnt); return cnt; } final ByteBuffer buf3 = buffers[offs + 2]; final int pos3 = buf3.position(); final int lim3 = buf3.limit(); final boolean dir3 = buf3.isDirect(); if (len == 3) { final long cnt; if (dir1 && dir2 && dir3) { cnt = testAndThrowWrite(writeDDD(fd, buf1, pos1, lim1, buf2, pos2, lim2, buf3, pos3, lim3)); } else if (!dir1 && !dir2 && !dir3) { final int off1 = buf1.arrayOffset(); final int off2 = buf2.arrayOffset(); final int off3 = buf3.arrayOffset(); cnt = testAndThrowWrite(writeHHH(fd, buf1.array(), pos1 + off1, lim1 + off1, buf2.array(), pos2 + off2, lim2 + off2, buf3.array(), pos3 + off3, lim3 + off3)); } else { cnt = testAndThrowWrite(writeMisc(fd, buffers, offs, len)); } if (cnt > 0L) { if (pos1 + cnt <= lim1) { buf1.position(pos1 + (int) cnt); } else if (pos1 + cnt - lim1 <= lim2) { buf1.position(lim1); buf2.position(pos2 + (int) (cnt - (lim1 - pos1))); } else { buf1.position(lim1); buf2.position(lim2); buf3.position(pos3 + (int) (cnt - (lim1 - pos1 + lim2 - pos2))); } } if (EXTRA_TRACE) log.tracef("Write(%d): %d", fd, cnt); return cnt; } final long cnt = testAndThrowWrite(writeMisc(fd, buffers, offs, len)); Buffers.trySkip(buffers, offs, len, cnt); if (EXTRA_TRACE) log.tracef("Write(%d): %d", fd, cnt); return cnt; } // receive static native int recvDirect(final int fd, ByteBuffer buffer, byte[] srcAddr, byte[] destAddr, Object keepAlive); static native int recvHeap(final int fd, byte[] bytes, int offs, int len, int pos, int lim, byte[] srcAddr, byte[] destAddr, Object keepAlive); static native int recvMisc(final int fd, ByteBuffer[] buffers, int offs, int len, byte[] srcAddr, byte[] destAddr, Object keepAlive); // send static native int sendDirect(final int fd, ByteBuffer buffer, int[] posAndLimit, byte[] destAddr, Object keepAlive); static native int sendHeap(final int fd, byte[] bytes, int offs, int len, byte[] destAddr, Object keepAlive); static native int sendMisc(final int fd, ByteBuffer[] buffers, int offs, int len, byte[] destAddr, Object keepAlive); // transfer static native long xferHeap(final int srcFd, byte[] bytes, int[] posAndLimit, int destFd, Object keepAlive); static native long xferDirect(final int srcFd, ByteBuffer buffer, int[] posAndLimit, int destFd, Object keepAlive); static native long sendfile(final int dest, FileChannel src, long offset, long length, Object keepAlive); // util static native int socketPair(int[] fds, Object keepAlive); static native int socketTcp(Object keepAlive); static native int socketTcp6(Object keepAlive); static native int socketUdp(Object keepAlive); static native int socketUdp6(Object keepAlive); static native int socketLocalStream(Object keepAlive); static native int socketLocalDatagram(Object keepAlive); static native int pipe(int[] fds, Object keepAlive); static native int bind(int fd, byte[] address, Object keepAlive); static native int accept(int fd, Object keepAlive); static native int connect(int fd, byte[] peerAddress, Object keepAlive); static native int listen(int fd, int backlog, Object keepAlive); static native int finishConnect(int fd, Object keepAlive); // options static native int getOptBroadcast(int fd, Object keepAlive); static native int setOptBroadcast(int fd, boolean enabled, Object keepAlive); static native int getOptDontRoute(int fd, Object keepAlive); static native int setOptDontRoute(int fd, boolean enabled, Object keepAlive); static native int getOptKeepAlive(int fd, Object keepAlive); static native int setOptKeepAlive(int fd, boolean enabled, Object keepAlive); static native int getOptCloseAbort(int fd, Object keepAlive); static native int setOptCloseAbort(int fd, boolean enabled, Object keepAlive); static native int getOptOobInline(int fd, Object keepAlive); static native int setOptOobInline(int fd, boolean enabled, Object keepAlive); static native int getOptReceiveBuffer(int fd, Object keepAlive); static native int setOptReceiveBuffer(int fd, int size, Object keepAlive); static native int getOptReuseAddr(int fd, Object keepAlive); static native int setOptReuseAddr(int fd, boolean enabled, Object keepAlive); static native int getOptSendBuffer(int fd, Object keepAlive); static native int setOptSendBuffer(int fd, int size, Object keepAlive); static native int getOptDeferAccept(int fd, Object keepAlive); static native int setOptDeferAccept(int fd, boolean enabled, Object keepAlive); static native int getOptMaxSegSize(int fd, Object keepAlive); static native int setOptMaxSegSize(int fd, int size, Object keepAlive); static native int getOptTcpNoDelay(int fd, Object keepAlive); static native int setOptTcpNoDelay(int fd, boolean enabled, Object keepAlive); static native int getOptMulticastTtl(int fd, Object keepAlive); static native int setOptMulticastTtl(int fd, boolean enabled, Object keepAlive); // linux static final int EPOLL_FLAG_READ = 0b0000_0001; static final int EPOLL_FLAG_WRITE = 0b0000_0010; static final int EPOLL_FLAG_EDGE = 0b0000_0100; static native int eventFD(Object keepAlive); static native int epollCreate(Object keepAlive); static native int epollWait(final int efd, long[] events, int timeout, Object keepAlive); static native int epollCtlAdd(final int efd, final int fd, final int flags, final int id, Object keepAlive); static native int epollCtlMod(final int efd, final int fd, final int flags, final int id, Object keepAlive); static native int epollCtlDel(final int efd, final int fd, Object keepAlive); static native int createTimer(final int seconds, final int nanos, Object keepAlive); static native long spliceToFile(int src, FileChannel dest, long destOffs, long length, Object keepAlive); static native long transfer(final int srcFd, final long count, final ByteBuffer throughBuffer, final int destFd, Object keepAlive); static native long tee(int src, int dest, long length, boolean more, Object keepAlive); static native int readTimer(final int fd, Object keepAlive); // utilities static IOException exceptionFor(int err) { String msg = strError(err); return new IOException(msg); } static int testAndThrowRead(int res) throws IOException { return res == -EAGAIN ? 0 : res == -EBADF ? -1 : res == 0 ? -1 : testAndThrow(res); } static long testAndThrowRead(long res) throws IOException { return res == -EAGAIN ? 0L : res == -EBADF ? -1L : res == 0 ? -1L : testAndThrow(res); } static int testAndThrowWrite(int res) throws IOException { if (res == -EBADF || res == 0) { throw new ClosedChannelException(); } return res == -EAGAIN ? 0 : testAndThrow(res); } static long testAndThrowWrite(long res) throws IOException { if (res == -EBADF || res == 0L) { throw new ClosedChannelException(); } return res == -EAGAIN ? 0L : testAndThrow(res); } static int testAndThrow(int res) throws IOException { if (res < 0) throw exceptionFor(res); return res; } static long testAndThrow(long res) throws IOException { if (res < 0) throw exceptionFor((int) res); return res; } static int testAndThrowConnect(int res) throws IOException { if (res == -EAGAIN) return 0; if (res < 0) throw exceptionFor(res); return res; } @SuppressWarnings({ "deprecation" }) static SocketAddress getSocketAddress(byte[] bytes) { if (bytes == null) { return null; } switch (bytes[0]) { case 0: { // inet 4 try { return new InetSocketAddress(InetAddress.getByAddress(Arrays.copyOfRange(bytes, 1, 5)), (((bytes[5]) & 0xff) << 8) | ((bytes[6]) & 0xff)); } catch (UnknownHostException e) { // ??? return null; } } case 1: { // inet 6 try { return new InetSocketAddress( Inet6Address.getByAddress( null, Arrays.copyOfRange(bytes, 1, 17), (bytes[19] & 0xff) << 24 | (bytes[20] & 0xff) << 16 | (bytes[21] & 0xff) << 8 | (bytes[22] & 0xff) ), (((bytes[17]) & 0xff) << 8) | ((bytes[18]) & 0xff)); } catch (UnknownHostException e) { // ??? return null; } } case 2: { // local int len = bytes[1] & 0xff; return new LocalSocketAddress(new String(bytes, 0, 2, len - 2)); } default: { return null; } } } private static final byte[] INVALID_ADDR = { (byte) 0xff }; static byte[] encodeSocketAddress(SocketAddress src) { if (src == null) { return INVALID_ADDR; } if (src instanceof InetSocketAddress) { final InetSocketAddress inet = (InetSocketAddress) src; final int port = inet.getPort(); final InetAddress address = inet.getAddress(); if (address instanceof Inet4Address) { final Inet4Address inet4 = (Inet4Address) address; final byte[] bytes = inet4.getAddress(); final byte[] result = new byte[7]; result[0] = 0; System.arraycopy(bytes, 0, result, 1, 4); result[5] = (byte) (port >> 8); result[6] = (byte) port; return result; } else if (address instanceof Inet6Address) { final Inet6Address inet6 = (Inet6Address) address; final byte[] bytes = inet6.getAddress(); final byte[] result = new byte[23]; result[0] = 1; System.arraycopy(bytes, 0, result, 1, 16); result[17] = (byte) (port >> 8); result[18] = (byte) port; final int scopeId = inet6.getScopeId(); result[19] = (byte) (scopeId >> 24); result[20] = (byte) (scopeId >> 16); result[21] = (byte) (scopeId >> 8); result[22] = (byte) scopeId; return result; } else { return INVALID_ADDR; } } else if (src instanceof LocalSocketAddress) { return encodeSocketAddress((LocalSocketAddress) src); } else { return INVALID_ADDR; } } static byte[] encodeSocketAddress(LocalSocketAddress local) { final String name = local.getName(); final byte[] result = new byte[2 + UNIX_PATH_LEN]; result[0] = 2; if (! encodeTo(name, result, 1)) { return INVALID_ADDR; } return result; } static boolean encodeTo(String src, byte[] dest, int offs) { final int srcLen = src.length(); try { for (int i = 0; i < srcLen; i = src.offsetByCodePoints(i, 1)) { int cp = src.codePointAt(i); if (cp > 0 && cp <= 0x7f) { // don't accidentally null-terminate the string dest[offs ++] = (byte) cp; } else if (cp <= 0x07ff) { dest[offs ++] = (byte)(0xc0 | 0x1f & cp >> 6); dest[offs ++] = (byte)(0x80 | 0x3f & cp); } else if (cp <= 0xffff) { dest[offs ++] = (byte)(0xe0 | 0x0f & cp >> 12); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 6); dest[offs ++] = (byte)(0x80 | 0x3f & cp); } else if (cp <= 0x1fffff) { dest[offs ++] = (byte)(0xf0 | 0x07 & cp >> 18); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 12); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 6); dest[offs ++] = (byte)(0x80 | 0x3f & cp); } else if (cp <= 0x3ffffff) { dest[offs ++] = (byte)(0xf8 | 0x03 & cp >> 24); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 18); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 12); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 6); dest[offs ++] = (byte)(0x80 | 0x3f & cp); } else if (cp >= 0) { dest[offs ++] = (byte)(0xfc | 0x01 & cp >> 30); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 24); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 18); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 12); dest[offs ++] = (byte)(0x80 | 0x3f & cp >> 6); dest[offs ++] = (byte)(0x80 | 0x3f & cp); } else { return false; } } return true; } catch (ArrayIndexOutOfBoundsException e) { return false; } } static void forceInit() { // no operation } static class BooleanPropertyAction implements PrivilegedAction<Boolean> { private final String key; BooleanPropertyAction(final String key) { this.key = key; } public Boolean run() { return Boolean.valueOf(System.getProperty(key, "false")); } } }